package org.codetranslators.compiler.abstractassembly;

import java.util.Vector;

import org.codetranslators.common.Temp;

public class AssemMove extends AssemStm
{
	private AssemExp dst, src;
	
	public AssemMove(AssemExp d, AssemExp s)
	{
		dst = d;
		src = s;
	}
	  
	public AssemExpList children() 
	{
		if (dst instanceof AssemMemory)
		   return new AssemExpList(((AssemMemory)dst).getMemExp(), new AssemExpList(src,null));
		else return new AssemExpList(src,null);
	 }

	public String getDescription()
	{
		return "Move";
	}

	public AssemExp getDst() {
		return dst;
	}

	public AssemExp getSrc() {
		return src;
	}
	
	public AssemStm build(AssemExpList list)
	{
		if (dst instanceof AssemMemory)
			   return new AssemMove(new AssemMemory(list.getHead()), list.getTail().getHead());
			else return new AssemMove(dst, list.getHead());
	}
	
	public AssemStm canonize()
	{		
		AssemStm retStm = null;
		
		AssemSeqExp destSeqExp = dst.canonize();
		AssemSeqExp srcSeqExp = src.canonize();
		
		AssemStm destSeqExpStm = destSeqExp.getStm();
		AssemStm srcSeqExpStm = srcSeqExp.getStm();
		
		AssemExp destSeqExpExp = destSeqExp.getExp();
				
		AssemStm stm = null;
		if(destSeqExpStm == null)
		{
			if(destSeqExpExp instanceof AssemMemory)
			{
				AssemMemory mem = (AssemMemory) destSeqExpExp;
				Temp temp = new Temp();
				AssemTemp assemTemp = new AssemTemp(temp);
				AssemMove newMoveStm = new AssemMove(assemTemp, mem.getMemExp());
				stm = new AssemSeq(newMoveStm, srcSeqExpStm);
				retStm = new AssemSeq(stm,
						new AssemMove(new AssemMemory(assemTemp), srcSeqExp.getExp()));
			}
			else
			{
				stm = srcSeqExpStm;
				retStm = new AssemSeq(stm, new AssemMove(destSeqExpExp, srcSeqExp.getExp()));
			}

		}
		else
		{
			if(destSeqExpExp instanceof AssemMemory)
			{
				AssemMemory mem = (AssemMemory) destSeqExpExp;
				Temp temp = new Temp();
				AssemTemp assemTemp = new AssemTemp(temp);
				AssemMove newMoveStm = new AssemMove(assemTemp, mem.getMemExp());
				AssemSeq tempSeq = new AssemSeq(destSeqExpStm, newMoveStm);
				stm = new AssemSeq(tempSeq, srcSeqExpStm);
				retStm = new AssemSeq(stm,
						new AssemMove(new AssemMemory(assemTemp), srcSeqExp.getExp()));
			}
			else
			{
				if(srcSeqExpStm == null) //stm = new MipsAssemSeq(destSeqExpStm, newMoveStm);
					retStm = destSeqExpStm;
				else
				{
					retStm = new AssemSeq(destSeqExpStm, srcSeqExpStm);
				}
			}
		}
		//return new MipsAssemSeq(stm,
		//				new MipsAssemMove(assemTemp, srcSeqExp.getExp()));
		//return new MipsAssemSeq(stm, new MipsAssemMove(destSeqExpExp, srcSeqExp.getExp()));
		return retStm;
	}
	
	public int getStmType()
	{
		return AssemStm.MOVE;
	}
	
	public Vector getChildren()
	{
		Vector ret = new Vector();
		ret.addElement(dst);
		ret.add(src);
		return ret;
	}
}
